home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Camelot
/
Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].zip
/
Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].adf
/
AmigaUUCP
/
dnews
/
group.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-02
|
9KB
|
546 lines
/*
* GROUP.C
*
*/
#include "defs.h"
Prototype void LoadGroups(char *);
Prototype void UnloadGroups(char *);
Prototype void CreateNewsrc(char *);
Prototype void RangeAdd(Range **, short, short);
Prototype void RangeDel(Range **, short, short);
Prototype int NextInRange(Range *, short);
Prototype int NextNotInRange(Range *, short);
Prototype void ClearGroupCache(NGroup *);
Prototype FNode **FindFNCache(FNode **, long);
Prototype void AddFNCache(FNode **, long, char *);
Prototype NGroup *PrevGroup(NGroup *);
Prototype NGroup *LastGroup(void);
Local void cns_tag(char *, char *, FILE *);
Local char *fgetstring(FILE *);
Local Range *ReadRange(FILE *);
Local void WriteRange(FILE *, Range *);
Local void FreeRange(Range *);
Local void PrintRange(Range *);
Local long GetMaxArtNo(char *);
Local void ClearGroupChain(FNode *);
Local void CreateFNCache(FNode ***);
static FNode *FreeFNBase;
extern NGroup *GBase;
/*
* LoadGroups()
*
* Load the newsrc file for the specified user and check for new groups
*/
void
LoadGroups(user)
char *user;
{
FILE *fi;
char buf[64];
NGroup *ng;
NGroup **png = &GBase;
sprintf(buf, "%s.dnewsrc", user);
if (fi = openlib(buf)) {
short c;
while ((c = fgetc(fi)) != EOF) {
switch(c) {
case '\n':
continue;
case 'y':
case 'n':
ng = malloc(sizeof(NGroup));
setmem(ng, sizeof(NGroup), 0);
if (c == 'y')
ng->Enabled = 1;
ng->Name = fgetstring(fi);
ng->RList= ReadRange(fi);
ng->MList= ReadRange(fi);
ng->KList= ReadRange(fi);
CreateFNCache(&ng->IdBase);
CreateFNCache(&ng->RefBase);
CreateFNCache(&ng->SubBase);
ng->CurNo = NextNotInRange(ng->RList, 0);
ng->MaxNo = GetMaxArtNo(ng->Name);
if (ng->CurNo > ng->MaxNo)
ng->CurNo = ng->MaxNo;
while (ng->CurNo < ng->MaxNo && !FileExists(FileForArticle(ng, ng->CurNo))) {
RangeAdd(&ng->RList, ng->CurNo, ng->CurNo);
ng->CurNo = NextNotInRange(ng->RList, ng->CurNo);
}
*png = ng;
png = &ng->Next;
break;
default:
puts("dnewsrc format error");
break;
}
/*
* skip to next newline.
*/
while ((c = fgetc(fi)) != EOF && c != '\n');
}
*png = NULL;
fclose(fi);
}
}
void
UnloadGroups(user)
char *user;
{
FILE *fi;
char buf[64];
NGroup *grp;
NGroup *gnext;
sprintf(buf, "%s.dnewsrc", user);
fi = openlib_write(buf);
if (fi == NULL)
printf("Unable to open %s\n", buf);
for (grp = GBase; grp; grp = gnext) {
gnext = grp->Next;
if (fi) {
if (grp->Enabled)
fputc('y', fi);
else
fputc('n', fi);
fprintf(fi, " %-20s ", grp->Name);
WriteRange(fi, grp->RList);
fputc(' ', fi);
WriteRange(fi, grp->MList);
fputc(' ', fi);
WriteRange(fi, grp->KList);
fputc('\n', fi);
}
free(grp->Name);
FreeRange(grp->RList);
FreeRange(grp->MList);
FreeRange(grp->KList);
free(grp);
}
if (fi)
fclose(fi);
GBase = NULL;
}
/*
* Create a new Newsrc file for a user
*/
void
CreateNewsrc(user)
char *user;
{
char buf[64];
FILE *fi;
sprintf(buf, "%s.dnewsrc", user);
if (fi = openlib_write(buf)) {
ScanNewsDirs(cns_tag, fi);
fclose(fi);
}
}
static void
cns_tag(path, tail, fi)
char *path;
char *tail;
FILE *fi;
{
FILE *fj;
sprintf(TmpBuf, "%s/.next", path);
if (fj = fopen(TmpBuf, "r")) {
int artno;
if (fscanf(fj, "%d", &artno) == 1) {
artno -= 50;
if (artno < 0)
artno = 0;
fprintf(fi, "y %-20s 0-%d - -\n", tail, artno);
printf("Adding %s\n", tail);
}
fclose(fj);
}
}
/*
* support
*/
static char *
fgetstring(fi)
FILE *fi;
{
char buf[128];
short i = 0;
short c;
while ((c = fgetc(fi)) == ' ' || c == 9);
while (c != EOF && c != ' ' && c != 9 && i < sizeof(buf) - 1) {
buf[i++] = c;
c = fgetc(fi);
}
buf[i] = 0;
if (c != EOF)
ungetc(c, fi);
return(strdup(buf));
}
static Range *
ReadRange(fi)
FILE *fi;
{
Range *rb;
Range **rp = &rb;
short c;
short is, ie;
while ((c = fgetc(fi)) == ' ' || c == 9);
if (c == '-') /* no range */
return(NULL);
while (c != EOF) {
is = 0;
while (c >= '0' && c <= '9') {
is = is * 10 + c - '0';
c = getc(fi);
}
if (c == '-') {
ie = 0;
c = getc(fi);
while (c >= '0' && c <= '9') {
ie = ie * 10 + c - '0';
c = getc(fi);
}
} else {
ie = is;
}
{
Range *r = malloc(sizeof(Range));
r->SNo = is;
r->ENo = ie;
*rp = r;
rp = &r->Next;
}
if (c != ',')
break;
c = fgetc(fi);
}
if (c != EOF)
ungetc(c, fi);
*rp = NULL;
return(rb);
}
static void
WriteRange(fi, r)
FILE *fi;
Range *r;
{
short first = 1;
if (r == NULL) {
fputc('-', fi);
return;
}
while (r) {
if (!first)
putc(',', fi);
if (r->SNo == r->ENo)
fprintf(fi, "%d", r->SNo);
else
fprintf(fi, "%d-%d", r->SNo, r->ENo);
first = 0;
r = r->Next;
}
}
void
RangeAdd(rp, sno, eno)
Range **rp;
short sno;
short eno;
{
Range *r;
Range *rn;
for (r = *rp; r; r = *rp) {
if (eno < r->SNo - 1) { /* insert before */
rn = malloc(sizeof(Range));
*rp = rn;
rn->Next = r;
rn->SNo = sno;
rn->ENo = eno;
return;
}
if (sno <= r->ENo + 1) { /* extend this ran */
if (sno < r->SNo)
r->SNo = sno;
if (eno > r->ENo)
r->ENo = eno;
/*
* delete/combine later rans that the new range overlaps
*/
while ((rn = r->Next) && r->ENo >= rn->SNo - 1) {
if (r->ENo < rn->ENo)
r->ENo = rn->ENo;
r->Next = rn->Next;
free(rn);
}
return;
}
rp = &r->Next;
}
/*
* Append to end
*/
rn = malloc(sizeof(Range));
rn->Next = NULL;
rn->SNo = sno;
rn->ENo = eno;
*rp = rn;
}
void
RangeDel(rp, sno, eno)
Range **rp;
short sno;
short eno;
{
Range *r;
Range *rn;
for (r = *rp; r; r = *rp) {
if (sno <= r->ENo && eno >= r->SNo) {
if (sno <= r->SNo && eno >= r->ENo) { /* delete entirely */
*rp = r->Next;
free(r);
continue;
} else if (sno > r->SNo && eno < r->ENo) { /* split */
rn = malloc(sizeof(Range));
rn->Next = r->Next;
r->Next = rn;
rn->ENo = r->ENo;
r->ENo = sno - 1;
rn->SNo = eno + 1;
break;
} else if (sno <= r->SNo) { /* else reduce an end */
r->SNo = eno + 1;
} else if (eno >= r->ENo) {
r->ENo = sno - 1;
}
} else {
if (eno < r->SNo) /* done */
break;
}
rp = &r->Next;
}
}
/*
* Returns index after idx that is in the range
*/
int
NextInRange(r, idx)
Range *r;
short idx;
{
while (r && idx >= r->ENo)
r = r->Next;
if (r) {
if (idx < r->SNo)
return(r->SNo);
return(idx + 1);
}
return(-1);
}
/*
* Returns index after idx that is not in the range
*/
int
NextNotInRange(r, idx)
Range *r;
short idx;
{
while (r && idx >= r->ENo)
r = r->Next;
if (r) {
if (idx < r->SNo - 1)
return(idx + 1);
return(r->ENo + 1);
}
return(idx + 1);
}
static void
FreeRange(r)
Range *r;
{
Range *rn;
while (r) {
rn = r->Next;
free(r);
r = rn;
}
}
/*
* debugging
*/
static void
PrintRange(r)
Range *r;
{
WriteRange(stdout, r);
puts("");
}
static long
GetMaxArtNo(group)
char *group;
{
FILE *fi;
int max = 0;
sprintf(TmpBuf, "%s/.next", MakeConfigPath(UUNEWS, group));
if (fi = fopen(TmpBuf, "r")) {
fscanf(fi, "%d", &max);
fclose(fi);
}
return(max);
}
/*
* References: and Message-ID: cache
*/
void
ClearGroupCache(grp)
NGroup *grp;
{
FNode **fn;
short i;
if (grp->IdBase) {
for (fn = grp->IdBase, i = 0; i < FNHASHSIZE; ++i, ++fn) {
ClearGroupChain(*fn);
*fn = NULL;
}
}
if (grp->RefBase) {
for (fn = grp->RefBase, i = 0; i < FNHASHSIZE; ++i, ++fn) {
ClearGroupChain(*fn);
*fn = NULL;
}
}
if (grp->SubBase) {
for (fn = grp->SubBase, i = 0; i < FNHASHSIZE; ++i, ++fn) {
ClearGroupChain(*fn);
*fn = NULL;
}
}
}
void
ClearGroupChain(fn)
FNode *fn;
{
FNode *fnext;
while (fn) {
fnext = fn->Next;
if (fn->Id)
free(fn->Id);
free(fn);
fn = fnext;
}
}
void
CreateFNCache(pht)
FNode ***pht;
{
if (*pht == NULL) {
*pht = malloc(FNHASHSIZE * sizeof(FNode *));
setmem(*pht, FNHASHSIZE * sizeof(FNode *), 0);
}
}
FNode **
FindFNCache(htab, msgno)
FNode **htab;
{
FNode **pfn = htab + (msgno & FNHASHMASK);
FNode *fn;
if (htab == NULL)
return(NULL);
while (fn = *pfn) {
if (fn->MsgNo == msgno)
break;
pfn = &fn->Next;
}
return(pfn);
}
void
AddFNCache(pfn, msgno, id)
FNode **pfn;
long msgno;
char *id;
{
FNode *fn = malloc(sizeof(FNode));
if (fn) {
*pfn = fn;
fn->MsgNo = msgno;
fn->Id = id;
fn->Next = NULL;
}
}
NGroup *
PrevGroup(grp)
NGroup *grp;
{
NGroup *gp2;
for (gp2 = GBase; gp2 && gp2->Next != grp; gp2 = gp2->Next);
return(gp2);
}
NGroup *
LastGroup()
{
NGroup *grp;
for (grp = GBase; grp && grp->Next; grp = grp->Next);
return(grp);
}